"""
作用：对selenium进行二次封装，供怕个包中的类继承
类名：Base
方法：
    __init__:创建webdriver对象
    get:请求目标网址
    find_element:单个元素定位
    find_elements:多个元素定位
    send_keys:输入内容
    click:点击
    text:获取标签文本

    quit:退出浏览器
"""
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import InvalidArgumentException, WebDriverException, TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.select import Select

# 打开浏览器驱动,返回webdriver对象
def get_driver(browser='chrome'):
    if browser == 'chrome':
        return webdriver.Chrome()
    else:
        return webdriver.Firefox()


class Base:

    def __init__(self, driver):
        """
        # 初始化webdriver对象
        """
        self.driver = driver
        sleep(1)

    def get(self, url):
        """
        # 封装访问方法
        :param url:
        :return:
        """
        try:
            self.driver.get(url)
            self.driver.implicitly_wait(4)
        except (InvalidArgumentException, WebDriverException) as e:
            print(e)

    def find_element(self, locator, timeout=5, poll_frequency=0.5):
        """
        # 封装定位单个元素方法
        :param locator:
        :param timeout:
        :param poll_frequency:
        :return:
        """
        try:
            return WebDriverWait(self.driver, timeout, poll_frequency).until(EC.presence_of_element_located(locator), message='单个元素定位错误')
        except (InvalidArgumentException, WebDriverException) as e:
            print(e)

    def find_elements(self, locator, timeout=5, poll_frequency=0.5):
        """
        封装定位多个元素的方法
        :param locator:
        :param timeout:
        :param poll_frequency:
        :return:
        """
        try:
            return WebDriverWait(self.driver, timeout, poll_frequency).until(EC.presence_of_all_elements_located(locator), message='多个元素定位错误')
        except (InvalidArgumentException, WebDriverException) as e:
            print(e)

    def send_keys(self, locator, content):
        """
        封装输入内容方法
        :param locator:
        :param content:
        :return:
        """
        sk_webelement = self.find_element(locator)
        if sk_webelement:
            return sk_webelement.send_keys(content)

    def click(self, locator):
        """
        封装click方法
        :param locator:
        :return:
        """
        cl_webelement = self.find_element(locator)
        if cl_webelement:
            return cl_webelement.click()

    def text(self, locator):
        """
        封装获取标签文本方法
        :param locator:
        :return:
        """
        text_element = self.find_element(locator)
        if text_element:
            return text_element.text

    def iframe(self, locator, index: int = 0):
        """
        进入iframe
        :param :
        :return:
        """
        try:
            self.driver.switch_to.frame(index)
        except:
            print(f'元素{locator}不存在,未找到')

    def switch_to_frame(self, locator):
        """
        封装切换frame的方法
        :param locator:
        :return:
        """
        frame_element = self.find_element(locator)
        return self.driver.switch_to.frame(frame_element)

    def iframe_element(self, locator):  # 定义一个用元素进入iframe的方法
        try:
            element = self.find_element(locator)  #
            self.driver.switch_to.frame(element)
        except:
            print(f'没有找到{locator}元素,无法获取元素属性值')  #

    def default_iframe(self):  # 定义一个直接退出iframe的方法
        self.driver.switch_to.default_content()

    def switch_to_window(self, i):
        """
        封装切换window的方法
        :param i: 0为第一次get打开的页面，1为第二次get打开的页面
        :return:
        """
        handles_list = self.driver.window_handles()
        return self.driver.switch_to.window(handles_list[i])

    def refresh(self):
        return self.driver.refresh()

    def forward(self):
        return self.driver.forward()

    def back(self):
        return self.driver.back()

    def alert_accept(self):
        # 系统弹窗处理，确定
        alert = self.driver.switch_to.alert
        alert.accept()

    def alert_dismiss(self):
        # 系统弹窗处理，取消
        alert = self.driver.switch_to.alert
        alert.dismiss()

    def select(self, locator, value):
        """
        通过value值选择下拉框中options选项
        :param locator: select元素定位
        :param value: options的value属性
        :return:
        """
        select_element = self.find_element(locator)
        select_element.select_by_value(value)

    def select_index(self, locator, index: int = 1):  # 定义一个用索引号选择下拉框选项的方法
        try:
            element = self.find_element(locator)
            select = Select(element)
            select.select_by_index(index)
        except:
            print(f'元素{locator}没找到')

    def clear(self, locator):  # 定义一个清空输入框方法
        try:
            element = self.find_element(locator)
            element.clear()
        except:
            print(f'元素{locator}没找到，无法点击')

    def radio(self, locator):
        """
        单选框选择
        :param locator:
        :return:
        """
        radio_element = self.find_element(locator)
        radio_element.click()

    def checkbox(self, locator, index):
        """
        定位checkbox元素列表，传入选项索引，单选checkbox中的选项
        :param locator: 定位checkbox元素，返回列表
        :param index: 选项在checkbox_elements中的索引
        :return:
        """
        checkbox_elements = self.find_elements(locator)
        checkbox_elements[index].click()

    def quit(self, seconds=3):
        sleep(seconds)
        self.driver.quit()


if __name__ == '__main__':
    driver = get_driver()
    case = Base(driver)
    case.get('https://www.baidu.com')
    case.find_element((By.ID, 'kw'))
    # case.send_keys((By.ID,'kw'),'天气预报')
    # case.click((By.ID,'su'))
    print(case.text((By.LINK_TEXT, '新闻')))
    case.quit()
